package com.xd.core.business.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xd.common.exception.XkdException;
import com.xd.common.util.SecurityUtil;
import com.xd.common.util.XkdUtil;
import com.xd.core.business.dto.RepaymentScheduleAppDto;
import com.xd.core.business.dto.RepaymentScheduleDto;
import com.xd.core.business.entity.RepaymentSchedule;
import com.xd.core.business.mapper.OutInfoMapper;
import com.xd.core.business.mapper.RepaymentScheduleMapper;
import com.xd.core.business.service.IRepaymentScheduleService;
import com.xd.core.business.vo.*;
import com.xd.core.company.dto.HomeQueryDto;
import com.xd.core.company.vo.DelayCounts;
import com.xd.core.debt.entity.Debt;
import com.xd.core.debt.mapper.DebtMapper;
import com.xd.core.finance.dto.KeepBookingDto;
import com.xd.core.note.eventEntity.DebtEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * <p>
 * 还款计划表 服务实现类
 * </p>
 *
 * @author ZX
 * @since 2025-02-28
 */
@Slf4j
@Service
public class RepaymentScheduleServiceImpl extends ServiceImpl<RepaymentScheduleMapper, RepaymentSchedule> implements IRepaymentScheduleService {

    @Autowired
    private RepaymentScheduleMapper repaymentScheduleMapper;
    @Autowired
    private DebtMapper debtMapper;
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    @Autowired
    private OutInfoMapper outInfoMapper;

    @Override
    public DelayCounts getDelayCounts(HomeQueryDto query) {
        Integer companyId = SecurityUtil.getLoginCompanyId();
        if (StringUtils.isEmpty(query.getStartTime()) && StringUtils.isEmpty(query.getEndTime())) {
            LocalDate today = LocalDate.now();
            LocalDate oneMonthAgo = today.minusMonths(1);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            query.setStartTime(oneMonthAgo.format(formatter));
            query.setEndTime(today.format(formatter));
        }

        return repaymentScheduleMapper.getDelayCounts(query, companyId);
    }

    @Override
    public RepaymentInfoVo getList(RepaymentScheduleDto repaymentScheduleDto) {
        PageHelper.startPage(repaymentScheduleDto.getPageNum(), repaymentScheduleDto.getPageSize());
        //业务详情,账单详情
        Page<BillInfoVo> billInfoVoPages = repaymentScheduleMapper.getList(repaymentScheduleDto);
        RepaymentInfoVo repaymentInfoVo = debtMapper.selectAmount(repaymentScheduleDto);
        if (ObjectUtil.isNotEmpty(repaymentInfoVo)) {
            repaymentInfoVo.setBillInfoVoPages(billInfoVoPages);
        }
        return repaymentInfoVo;
    }

    @Transactional
    @Override
    public void updateBook(KeepBookingDto keepBookingDto) {
        Debt debt = debtMapper.selectById(keepBookingDto.getDebtId());
        Integer remainingRepaymentPeriods = debt.getRemainingRepaymentPeriods();
        keepBookingDto.setPeriods(remainingRepaymentPeriods);
        if (!"1".equals(debt.getIsWithhold()) && !"1".equals(debt.getIsOfflineRepay())) {
            throw new XkdException("用户不满足还款记账的条件");
        }
        if ("0".equals(debt.getIsEarly())) {
            keepBookingDto.setDebtId(debt.getId());
            repaymentScheduleMapper.updateAmount(keepBookingDto);
            Integer id = keepBookingDto.getId();
            RepaymentSchedule repaymentSchedule = repaymentScheduleMapper.selectById(id);
            keepBookingDto.setInterest(repaymentSchedule.getInterest());
            keepBookingDto.setPrincipal(repaymentSchedule.getPrincipal());
            debtMapper.updateAmount1(keepBookingDto);
            //生产贷款结清证明  异步调用
            Integer status = debt.getStatus();
            if (status == 2) {
                eventPublisher.publishEvent(new DebtEvent(debt));
            }
        } else //提前还款
        {
            outInfoMapper.updateClearDate(debt.getOutId());
            debtMapper.updateAmount(keepBookingDto);
            repaymentScheduleMapper.updateStatusByOutId(debt.getOutId());
            //生产贷款结清证明  异步调用
            eventPublisher.publishEvent(new DebtEvent(debt));
        }
    }

    /**
     * @return com.xd.core.business.vo.RepayDetailVo
     * @description 还款详情信息
     * @author Zch
     * @date 20:12 2025/6/10 星期二
     **/
    @Override
    public RepayDetailVo getRepayDetail(RepaymentScheduleDto repaymentScheduleDto) {
        XkdUtil.checkNonNullProperties(repaymentScheduleDto, "incomingId", "outId");
        RepayDetailVo detail = repaymentScheduleMapper.getRepayDetail(repaymentScheduleDto);
        String montrayUnit = XkdUtil.number2CNMontrayUnit(new BigDecimal(detail.getOutLoan()));
        detail.setOutLoan(detail.getOutLoan() + "（" + montrayUnit + "）");
        return detail;
    }

    @Override
    public List<RepaymentScheduleList> getRepaymentScheduleList(Integer debtId) {
        XkdUtil.checkNonNullProperties(debtId);
        List<RepaymentScheduleList> scheduleList = repaymentScheduleMapper.getRepaymentScheduleList(debtId);
        for (RepaymentScheduleList list : scheduleList) {
            String bills = list.getHistoryBills();
            //将退保前账单转换为还款计划集合
            List<RepaymentSchedule> oldschedules = JSON.parseArray(bills, RepaymentSchedule.class);
            BigDecimal principal = oldschedules.stream().map(RepaymentSchedule::getPrincipal).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal interest = oldschedules.stream().map(RepaymentSchedule::getInterest).reduce(BigDecimal.ZERO, BigDecimal::add);
            list.setOrderAmount(principal).setOrderInterest(interest).setAmount(principal.add(interest));
        }
        return scheduleList;
    }

    @Override
    public RepaymentScheduleAppVo getOutRepaymentPlan(RepaymentScheduleAppDto repaymentScheduleAppDto) {
        PageHelper.startPage(repaymentScheduleAppDto.getPageNum(), repaymentScheduleAppDto.getPageSize());
        //业务详情,账单详情
        Page<BillInfoVo> billInfoVoPages = repaymentScheduleMapper.getAppList(repaymentScheduleAppDto.getIncomingId());
        RepaymentScheduleAppVo repaymentInfoVo = debtMapper.selectAppAmount(repaymentScheduleAppDto.getIncomingId());
        if (ObjectUtil.isNotEmpty(repaymentInfoVo)) {
            repaymentInfoVo.setBillInfoVoPages(billInfoVoPages);
        }
        return repaymentInfoVo;
    }

    @Override
    public RemainAmountVo getRemainAmount(RepaymentScheduleDto repaymentScheduleDto) {
        //根据放款id和进件id获取最新账单
        LambdaQueryWrapper<RepaymentSchedule> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(RepaymentSchedule::getOutId, repaymentScheduleDto.getOutId())
                .eq(RepaymentSchedule::getIncomingId, repaymentScheduleDto.getIncomingId());
        List<RepaymentSchedule> list = repaymentScheduleMapper.selectList(wrapper);
        //获取所有的应还本金和利息
        BigDecimal principal = list.stream().map(RepaymentSchedule::getPrincipal).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal interest = list.stream().map(RepaymentSchedule::getInterest).reduce(BigDecimal.ZERO, BigDecimal::add);
        RemainAmountVo remainAmountVo = new RemainAmountVo();
        remainAmountVo.setRemainingShouldRepayPrincipal(principal);
        remainAmountVo.setRemainingShouldRepayInterest(interest);
        remainAmountVo.setPrincipalAndInterest(principal.add(interest));
        return remainAmountVo;
    }
}


